home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
UTIL
/
FILEUTIL
/
SUPPORT100
/
Source
/
Joinf_c
< prev
next >
Wrap
Text File
|
1995-02-04
|
23KB
|
458 lines
/********************************************************************************/
/* */
/* Joinf.c */
/* Part of Splitf and Joinf distribution */
/* version 1.13, © 1993-1995 Adam Hamilton */
/* See the README file for copyright information */
/* */
/********************************************************************************/
/*********************************/
/* Include required header files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "config.h"
/**********************************/
/* Program macros and definitions */
#define TITLE "File joiner. Version 1.13 - 4th Feburary 1995 by A.Hamilton\n\n"
#ifndef Bool
# define Bool char
#endif
#define False 0
#define True !False
#define MIN(a, b) (a < b ? a : b)
#define MAX(a, b) (a > b ? a : b)
/********************************************************************************/
/* */
/* Function : usage */
/* Description : Displays program usage to standard error, and exits. */
/* Arguments : progname - pointer to character string containing the program */
/* name. */
/* Returns : None. */
/* */
/********************************************************************************/
void usage (char *progname)
{
fprintf (stderr, TITLE);
fprintf (stderr, "Usage : %s [options] <filename>\n\n", progname);
fprintf (stderr, "Options (can be abbreviated) :\n");
#ifndef PC
fprintf (stderr, " -buffersize [buffersize in K] default = 32\n");
#endif
fprintf (stderr, " -filename [new filename]\n");
fprintf (stderr, " -interactive\n");
fprintf (stderr, " -info\n");
exit (EXIT_FAILURE);
}
/********************************************************************************/
/* */
/* Function : examine_filename */
/* Description : Splits filename into component parts. */
/* Arguments : original_name - character array, filename to be examined. */
/* name - pointer to a character array in which to store */
/* file leafname (excluding extention). */
/* path - pointer to a character array in which to store */
/* the destination files path. */
/* Returns : If the destination file has an extention, then return it, */
/* otherwise return "". */
/* */
/********************************************************************************/
char *examine_filename (char original_name[], char *name, char *path)
{
char main_name[256]; /* Temporary store for leafname. */
char *original; /* Pointer to start of leafname. */
char ext[32];
char *pointer; /* Pointer to any ':' characters found. */
register int i = -1, n; /* Pointer & counter. */
if (COLON) /* If our system uses ':' in */
pointer = strrchr (original_name, ':'); /* the file path, then remember */
else /* where it is. */
pointer = NULL;
original = strrchr (original_name, SEPARATOR_SEARCH); /* Find the address where the */
if ((original = MAX (original, pointer)) == NULL) /* leafname starts. */
original = original_name;
else {
original++;
strncpy (path, original_name, original - original_name); /* Get the path. */
path[original - original_name] = '\0';
}
do {
i++;
main_name[i] = original[i]; /* Get files leafname */
} while (main_name[i] != '.' && main_name[i] != '\0'); /* (excluding any extention). */
main_name[i - 2] = '\0'; /* Copy the leafname. */
strcpy (name, main_name);
if (main_name[i] == '\0') /* If the file doesn't have an */
return (""); /* extention return an empty string. */
for (n = 0; (ext[n] = original[i]) != '\0'; n++, i++) ; /* Otherwise get the extention */
return (ext); /* and return it. */
}
/********************************************************************************/
/* */
/* Function : numtostr */
/* Description : Converts a number into a 2 didget character string. */
/* Arguments : number - number to be converted. */
/* name - pointer to a character array to store the number. */
/* Returns : None. */
/* */
/********************************************************************************/
void numtostr (short number, char *name)
{
name[0] = (short) (number / 10) + '0';
name[1] = (number % 10) + '0';
name[2] = '\0';
}
/********************************************************************************/
/* */
/* Function : main */
/* Description : Main control function. */
/* Arguments : Command line parameters. */
/* Returns : Exit status. */
/* */
/********************************************************************************/
int main (int argc, char *argv[])
{
char source_filename[256]; /* Source filename. */
char out_filename[256]; /* Output leafname. */
char in_path[256]; /* Input path. */
char file_ext[32]; /* Output extention. */
char out_name[256]; /* Full output filename. */
char header[50]; /* Output file header. */
char fnum[3]; /* Output part number. */
char *progname; /* Program name. */
char string[256]; /* Input string. */
char type[5]; /* Filetype (Acorn systems only). */
char interactive = 0; /* Interactive status flag. */
char source_name[256];
char check_name[256];
short file_number = 0; /* Current part number. */
short check_number;
long read_size = 32 * 1024; /* Buffer size (default 32K). */
long out_position; /* Position within output file. */
long in_position; /* Position within input file. */
long bytes_read; /* Number of bytes read. */
long bytes_written; /* Number of bytes written. */
long file_length; /* Length of source file. */
long *buffer; /* Pointer to buffer. */
int total_number; /* Total number of parts to join. */
int args; /* Number of command line arguments. */
int i, n; /* Counters. */
Bool info = False; /* Display information? */
FILE *source_file; /* Source file ID. */
FILE *out_file; /* Output file ID. */
static char splith1[]="Split:"; /* Part 1 header check string. */
static char splith2[]="Sp:"; /* Part >1 header check string. */
#ifdef ACORN
_kernel_swi_regs regs;
_kernel_oserror *err;
#endif
progname = *argv; /* Get the program name. */
in_path[0] = '\0'; /* Set path to CWD. */
out_filename[0] = '\0'; /* Clear destination filename. */
source_filename[0] = '\0'; /* Clear source filename. */
args = argc - 1; /* Initialise count of arguments. */
if (!args) usage (progname); /* If no arguments supplied, show usage.*/
while (args--) {
argv++; /* Look at next argument. */
if (!strncmp ("-filename", *argv, MAX (2, strlen (*argv)))) { /* -filename */
if (!args) {
fprintf (stderr, "Filename required\n\n");
usage (progname);
}
strcpy (out_filename, *++argv); /* Read output filename.*/
args--;
}
#ifndef PC
else if (!strncmp ("-buffersize", *argv, MAX (2, strlen (*argv)))) { /* -buffersize */
if (!args) {
fprintf (stderr, "Buffer size required\n\n");
usage (progname);
}
read_size = (long) atoi (*++argv) * 1024; /* Read buffer size. */
args--;
}
#endif
else if (!strncmp ("-interactive", *argv, MAX (2, strlen (*argv)))) /* -interactive */
interactive = 1;
else if (!strncmp ("-info", *argv, MAX (3, strlen (*argv)))) /* -info */
info = True;
else {
strcpy (source_filename, *argv); /* Read source filename.*/
if (args) usage (progname);
}
}
if (source_filename[0] == NULL) {
fprintf (stderr, "Source filename required\n\n");
usage (progname);
}
/* Get file detail from source filename.*/
strcpy (file_ext, examine_filename (source_filename, source_name, in_path));
source_file = fopen (source_filename, "rb"); /* Open read binary source file. */
if (source_file == NULL) { /* Report if error, and stop. */
fprintf (stderr, "Fatal error opening %s for input.\n", source_filename);
exit (EXIT_FAILURE);
}
i = 0; /* Initialise counter. */
while ((header[i++] = fgetc (source_file)) != '|' && i < 300) ; /* Read file header, */
for (i = 0; i < 6; i++) if (header[i] != splith1[i]) { /* and compare with template. */
fprintf (stderr,"Fatal error, no split header in file %s\n", source_filename);
fclose (source_file);
exit (EXIT_FAILURE);
}
fseek (source_file, 0L, SEEK_END); /* Set file pointer to end of file, */
file_length = ftell (source_file); /* get file length */
fseek (source_file, 0L, SEEK_SET); /* and reset pointer to the start. */
n = 0; /* Initialise counter. */
#ifdef ACORN
while (header[i] != '=') { /* Extract output filename, */
out_name[n++] = (header[i] == '.' ? '/' : header[i]); /* swapping any '.' and '/' */
i++; /* characters. */
}
n++;
i++;
#else
while ((out_name[n++] = header[i++]) != '=') ; /* Just extract the filename, */
#endif
out_name[--n] = '\0'; /* terminate it properly, */
if (out_filename[0] == '\0') strcpy (out_filename, out_name); /* and copy. */
n = 0; /* Initialise counter. */
while ((fnum[n++] = header[i++]) != '=') ; /* Get the total number of */
fnum[--n] = '\0'; /* parts. */
total_number = atoi (fnum);
n = 0; /* Initialise counter. */
while ((type[n++] = header[i++]) != '|') ; /* Read the filetype data. */
type[--n] = '\0';
if (info) { /* If -info selected, only */
printf (TITLE); /* print information. */
printf ("Information :\n\n");
printf (" Output filename is %s", out_filename);
#ifdef ACORN
if (type[0] == 't') { /* If the file contains */
printf (", filetype "); /* filetype data then show it. */
for (n = 1; type[n] != '\0'; n++)
printf ("%c", toupper(type[n]));
}
#endif
printf ("\n");
bytes_read = 0;
}
else { /* -info not selected, do the joining. */
buffer = (long *) malloc ((size_t) read_size); /* Allocate memory for a buffer. */
if (buffer == NULL) {
fprintf (stderr, "Fatal error, unable to allocate memory block of %ld bytes\n", read_size);
exit (EXIT_FAILURE);
}
printf ("Using buffer size of %ld bytes.\n", read_size);
#ifdef ACORN
regs.r[0] = 7; /* Create the file with SWI */
regs.r[1] = (int) out_filename; /* OS_File 7 */
regs.r[2] = 0xdeaddead;
regs.r[3] = 0xdeaddead;
regs.r[4] = 0;
regs.r[5] = (int) (file_length * (total_number - 0.5)); /* using an estimated size. */
if ((err = _kernel_swi (SWI_OS_File, ®s, ®s)) != NULL) {
fprintf (stderr, "Fatal error opening %s for output:\n-- %s\n", out_filename, err->errmess);
exit (EXIT_FAILURE);
}
#endif
out_file = fopen (out_filename, "wb"); /* Open output file. */
if (out_file == NULL) { /* Report if error, and stop. */
fprintf (stderr, "Fatal error opening %s for output.\n", out_filename);
exit (EXIT_FAILURE);
}
}
out_position = 0; /* Initialise output file position pointer. */
for (file_number = 1; file_number <= total_number; file_number++) { /* for each part */
numtostr (file_number, fnum);
while (interactive == 1 && file_number > 1) { /* If -interactive selected, */
printf ("Enter path for %s%s%s (Return for %s) :\n", /* ask for location of next */
source_name, fnum, file_ext, /* part. */
in_path[0] == '\0' ? "current directory" : in_path);
gets (string); /* Get output destination. */
if (strchr (string, ' ') != NULL) {
printf ("Invalid path name.\n");
continue;
}
if (string[0] != '\0') { /* If nothing entered, then use the default. */
strcpy (in_path, string);
i = strlen (in_path);
if (in_path[i - 1] != FILE_SEPARATOR)
if (!COLON || (COLON && in_path[i - 1] != ':')) {
in_path[i] = FILE_SEPARATOR;
in_path[i + 1] = '\0';
}
}
interactive = interactive | 2; /* Set flag to say data has been accepted. */
}
interactive = interactive & 1; /* Mask off unrequired data. */
/* Create the full input filename. */
sprintf (source_filename, "%s%s%s%s", in_path, source_name, fnum, file_ext);
if (file_number != 1) { /* If it's not the first part, */
source_file = fopen (source_filename, "rb"); /* Open read binary file. */
if (source_file == NULL) { /* Report if error, and stop. */
fprintf (stderr, "Fatal error opening %s for input.\n", source_filename);
exit (EXIT_FAILURE);
}
i = 0; /* Initialise counter. */
while ((header[i++] = fgetc (source_file)) != '|' && i<300) ; /* Check the header */
for (i = 0; i < 3; i++) if (header[i] != splith2[i]) { /* with a template. */
fprintf (stderr,"Fatal error, bad header in file %s\n", source_filename);
fclose (source_file);
exit (EXIT_FAILURE);
}
n = 0; /* Initialise counter. */
#ifdef ACORN
while (header[i] != '=') {
check_name[n++] = (header[i]=='.' ? '/' : header[i]); /* Swap '.' and '/' */
i++; /* characters and check */
} /* filename. */
n++;
i++;
#else
while ((check_name[n++] = header[i++]) != '=') ; /* Just check filename. */
#endif
check_name[--n] = '\0';
if (strcmp (out_name, check_name)) { /* Report if error */
fprintf (stderr,"Fatal error, split file %s does not match.\n", source_filename);
fclose (source_file);
exit (EXIT_FAILURE); /* and stop. */
}
n = 0; /* Initialise counter. */
while ((fnum[n++] = header[i++]) != '|') ;
fnum[--n] = '\0';
check_number = atoi (fnum); /* Get the part number */
if (check_number != file_number) { /* and make sure it's */
fprintf (stderr,"Fatal error, incorrect part.\n"); /* one we want. */
fclose (source_file);
exit (EXIT_FAILURE);
}
}
in_position = (long) i; /* Initialise the input file position pointer. */
fseek (source_file, 0L, SEEK_END); /* Set file pointer to end of file, */
file_length = ftell (source_file); /* get file length */
fseek (source_file, in_position, SEEK_SET); /* and reset pointer to start of data. */
if (info) { /* If -info just display information. */
printf (" %s...%ld bytes\n", source_filename, file_length - in_position);
bytes_read += file_length - in_position;
}
else { /* Otherwise, do the joining. */
printf ("Reading data from %s.....%ld bytes\n", source_filename, file_length - in_position);
while (file_length - in_position > 0) { /* If any data */
bytes_read = fread (buffer, 1, (size_t) read_size, source_file); /* left, read */
bytes_written = fwrite (buffer, 1, (size_t) bytes_read, out_file); /* and write. */
/* Check we've written the correct amount of data. */
if (bytes_written < read_size && bytes_written < file_length-in_position) {
fprintf (stderr, "Fatal error while writing %s\n", out_filename);
exit (EXIT_FAILURE); /* If unsucessfull, then stop. */
}
in_position += bytes_read; /* Update the file position */
out_position += bytes_written; /* pointers. */
}
}
fclose (source_file); /* Close the source file. */
if (!info && (bytes_written < bytes_read)) {
fprintf (stderr, "Fatal error while writing %s\n", out_filename);
exit (EXIT_FAILURE); /* If unsucessfull, stop. */
}
}
if (info)
printf ("\nTotal of %ld bytes contained in %d files.\n", bytes_read, total_number);
else {
fclose (out_file); /* Close output file */
free (buffer); /* and free buffer. */
#ifdef ACORN
if (type[0] == 't') { /* If the file had a type */
regs.r[0] = 18; /* set the filetype with SWI */
regs.r[1] = (int) out_filename; /* OS_File 18 */
sscanf (type, "t%x", ®s.r[2]);
err = _kernel_swi (SWI_OS_File, ®s, ®s);
}
#endif
/* Report status */
fprintf (stderr, "%ld bytes written to file %s\n", out_position, out_filename);
}
exit (EXIT_SUCCESS); /* and finish. */
}